From 96428d33d9b6f28ce02902eae1a480b1d8f0e713 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 1 Dec 2005 15:22:22 +0100 Subject: [PATCH] Define explicit evtchn_port_t type (32 bits) and plumb up to user space thru /dev/xen/evtchn. Signed-off-by: Keir Fraser --- .../drivers/xen/evtchn/evtchn.c | 82 +++++++------------ tools/console/daemon/io.c | 4 +- tools/ioemu/target-i386-dm/helper2.c | 6 +- tools/ioemu/vl.c | 2 +- tools/libxc/xc_evtchn.c | 2 +- tools/libxc/xenctrl.h | 2 +- tools/xenstore/fake_libxc.c | 2 +- tools/xenstore/xenstored_domain.c | 13 +-- xen/include/public/event_channel.h | 32 ++++---- 9 files changed, 64 insertions(+), 81 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c b/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c index b3201a984d..6c94cfa8c0 100644 --- a/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c +++ b/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c @@ -50,9 +50,9 @@ struct per_user_data { /* Notification ring, accessed via /dev/xen/evtchn. */ -#define EVTCHN_RING_SIZE 2048 /* 2048 16-bit entries */ +#define EVTCHN_RING_SIZE (PAGE_SIZE / sizeof(evtchn_port_t)) #define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1)) - u16 *ring; + evtchn_port_t *ring; unsigned int ring_cons, ring_prod, ring_overflow; /* Processes wait on this queue when ring is empty. */ @@ -75,7 +75,7 @@ void evtchn_device_upcall(int port) if ((u = port_user[port]) != NULL) { if ((u->ring_prod - u->ring_cons) < EVTCHN_RING_SIZE) { - u->ring[EVTCHN_RING_MASK(u->ring_prod)] = (u16)port; + u->ring[EVTCHN_RING_MASK(u->ring_prod)] = port; if (u->ring_cons == u->ring_prod++) { wake_up_interruptible(&u->evtchn_wait); kill_fasync(&u->evtchn_async_queue, @@ -94,52 +94,40 @@ static ssize_t evtchn_read(struct file *file, char __user *buf, { int rc; unsigned int c, p, bytes1 = 0, bytes2 = 0; - DECLARE_WAITQUEUE(wait, current); struct per_user_data *u = file->private_data; - add_wait_queue(&u->evtchn_wait, &wait); + /* Whole number of ports. */ + count &= ~(sizeof(evtchn_port_t)-1); - count &= ~1; /* even number of bytes */ - - if (count == 0) { - rc = 0; - goto out; - } + if (count == 0) + return 0; if (count > PAGE_SIZE) count = PAGE_SIZE; for (;;) { - set_current_state(TASK_INTERRUPTIBLE); + if (u->ring_overflow) + return -EFBIG; if ((c = u->ring_cons) != (p = u->ring_prod)) break; - if (u->ring_overflow) { - rc = -EFBIG; - goto out; - } - - if (file->f_flags & O_NONBLOCK) { - rc = -EAGAIN; - goto out; - } - - if (signal_pending(current)) { - rc = -ERESTARTSYS; - goto out; - } + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; - schedule(); + rc = wait_event_interruptible( + u->evtchn_wait, u->ring_cons != u->ring_prod); + if (rc) + return rc; } /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */ if (((c ^ p) & EVTCHN_RING_SIZE) != 0) { bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) * - sizeof(u16); - bytes2 = EVTCHN_RING_MASK(p) * sizeof(u16); + sizeof(evtchn_port_t); + bytes2 = EVTCHN_RING_MASK(p) * sizeof(evtchn_port_t); } else { - bytes1 = (p - c) * sizeof(u16); + bytes1 = (p - c) * sizeof(evtchn_port_t); bytes2 = 0; } @@ -153,32 +141,26 @@ static ssize_t evtchn_read(struct file *file, char __user *buf, if (copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) || ((bytes2 != 0) && - copy_to_user(&buf[bytes1], &u->ring[0], bytes2))) { - rc = -EFAULT; - goto out; - } - - u->ring_cons += (bytes1 + bytes2) / sizeof(u16); + copy_to_user(&buf[bytes1], &u->ring[0], bytes2))) + return -EFAULT; - rc = bytes1 + bytes2; + u->ring_cons += (bytes1 + bytes2) / sizeof(evtchn_port_t); - out: - __set_current_state(TASK_RUNNING); - remove_wait_queue(&u->evtchn_wait, &wait); - return rc; + return bytes1 + bytes2; } static ssize_t evtchn_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { int rc, i; - u16 *kbuf = (u16 *)__get_free_page(GFP_KERNEL); + evtchn_port_t *kbuf = (evtchn_port_t *)__get_free_page(GFP_KERNEL); struct per_user_data *u = file->private_data; if (kbuf == NULL) return -ENOMEM; - count &= ~1; /* even number of bytes */ + /* Whole number of ports. */ + count &= ~(sizeof(evtchn_port_t)-1); if (count == 0) { rc = 0; @@ -194,7 +176,7 @@ static ssize_t evtchn_write(struct file *file, const char __user *buf, } spin_lock_irq(&port_user_lock); - for (i = 0; i < (count/2); i++) + for (i = 0; i < (count/sizeof(evtchn_port_t)); i++) if ((kbuf[i] < NR_EVENT_CHANNELS) && (port_user[kbuf[i]] == u)) unmask_evtchn(kbuf[i]); spin_unlock_irq(&port_user_lock); @@ -379,8 +361,8 @@ static int evtchn_open(struct inode *inode, struct file *filp) memset(u, 0, sizeof(*u)); init_waitqueue_head(&u->evtchn_wait); - if ((u->ring = (u16 *)__get_free_page(GFP_KERNEL)) == NULL) - { + u->ring = (evtchn_port_t *)__get_free_page(GFP_KERNEL); + if (u->ring == NULL) { kfree(u); return -ENOMEM; } @@ -400,8 +382,7 @@ static int evtchn_release(struct inode *inode, struct file *filp) free_page((unsigned long)u->ring); - for (i = 0; i < NR_EVENT_CHANNELS; i++) - { + for (i = 0; i < NR_EVENT_CHANNELS; i++) { int ret; if (port_user[i] != u) continue; @@ -447,10 +428,9 @@ static int __init evtchn_init(void) spin_lock_init(&port_user_lock); memset(port_user, 0, sizeof(port_user)); - /* (DEVFS) create '/dev/misc/evtchn'. */ + /* Create '/dev/misc/evtchn'. */ err = misc_register(&evtchn_miscdev); - if (err != 0) - { + if (err != 0) { printk(KERN_ALERT "Could not register /dev/misc/evtchn\n"); return err; } diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c index 9aae032680..a26a6560dc 100644 --- a/tools/console/daemon/io.c +++ b/tools/console/daemon/io.c @@ -62,7 +62,7 @@ struct domain struct domain *next; char *conspath; int ring_ref; - int local_port; + evtchn_port_t local_port; int evtchn_fd; struct xencons_interface *interface; }; @@ -488,7 +488,7 @@ static void handle_tty_write(struct domain *dom) static void handle_ring_read(struct domain *dom) { - uint16_t v; + evtchn_port_t v; if (!read_sync(dom->evtchn_fd, &v, sizeof(v))) return; diff --git a/tools/ioemu/target-i386-dm/helper2.c b/tools/ioemu/target-i386-dm/helper2.c index 8a0305a2ba..d2a618c580 100644 --- a/tools/ioemu/target-i386-dm/helper2.c +++ b/tools/ioemu/target-i386-dm/helper2.c @@ -125,7 +125,7 @@ int evtchn_fd = -1; //the evtchn port for polling the notification, //should be inputed as bochs's parameter -uint16_t ioreq_remote_port, ioreq_local_port; +evtchn_port_t ioreq_remote_port, ioreq_local_port; //some functions to handle the io req packet void sp_info() @@ -170,12 +170,12 @@ ioreq_t* __cpu_get_ioreq(void) ioreq_t* cpu_get_ioreq(void) { int rc; - uint16_t port; + evtchn_port_t port; rc = read(evtchn_fd, &port, sizeof(port)); if ((rc == sizeof(port)) && (port == ioreq_local_port)) { // unmask the wanted port again - write(evtchn_fd, &ioreq_local_port, 2); + write(evtchn_fd, &ioreq_local_port, sizeof(port)); //get the io packet from shared memory return __cpu_get_ioreq(); diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index 8ba47307e5..be7108e91f 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -2907,7 +2907,7 @@ int main(int argc, char **argv) break; case QEMU_OPTION_p: { - extern uint16_t ioreq_remote_port; + extern evtchn_port_t ioreq_remote_port; ioreq_remote_port = atoi(optarg); fprintf(logfile, "eport: %d\n", ioreq_remote_port); } diff --git a/tools/libxc/xc_evtchn.c b/tools/libxc/xc_evtchn.c index ffc252ed5a..97cdac9548 100644 --- a/tools/libxc/xc_evtchn.c +++ b/tools/libxc/xc_evtchn.c @@ -51,7 +51,7 @@ int xc_evtchn_alloc_unbound(int xc_handle, int xc_evtchn_status(int xc_handle, uint32_t dom, - int port, + evtchn_port_t port, xc_evtchn_status_t *status) { int rc; diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index d12ac4993f..35b5dec1f2 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -334,7 +334,7 @@ int xc_evtchn_alloc_unbound(int xc_handle, int xc_evtchn_status(int xc_handle, uint32_t dom, /* may be DOMID_SELF */ - int port, + evtchn_port_t port, xc_evtchn_status_t *status); int xc_physdev_pci_access_modify(int xc_handle, diff --git a/tools/xenstore/fake_libxc.c b/tools/xenstore/fake_libxc.c index 14025ec089..06d272930c 100644 --- a/tools/xenstore/fake_libxc.c +++ b/tools/xenstore/fake_libxc.c @@ -34,7 +34,7 @@ static int sigfd; static int xs_test_pid; -static uint16_t port; +static evtchn_port_t port; /* The event channel maps to a signal, shared page to an mmapped file. */ void evtchn_notify(int local_port) diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c index d252469617..47683558e4 100644 --- a/tools/xenstore/xenstored_domain.c +++ b/tools/xenstore/xenstored_domain.c @@ -41,7 +41,7 @@ #include static int *xc_handle; -static int virq_port; +static evtchn_port_t virq_port; int eventchn_fd = -1; @@ -53,11 +53,11 @@ struct domain unsigned int domid; /* Event channel port */ - uint16_t port; + evtchn_port_t port; /* The remote end of the event channel, used only to validate repeated domain introductions. */ - uint16_t remote_port; + evtchn_port_t remote_port; /* The mfn associated with the event channel, used only to validate repeated domain introductions. */ @@ -224,7 +224,7 @@ static void domain_cleanup(void) /* We scan all domains rather than use the information given here. */ void handle_event(void) { - uint16_t port; + evtchn_port_t port; if (read(eventchn_fd, &port, sizeof(port)) != sizeof(port)) barf_perror("Failed to read from event fd"); @@ -314,7 +314,7 @@ void do_introduce(struct connection *conn, struct buffered_data *in) char *vec[3]; unsigned int domid; unsigned long mfn; - uint16_t port; + evtchn_port_t port; if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec)) { send_error(conn, EINVAL); @@ -460,7 +460,8 @@ void restore_existing_connections(void) static int dom0_init(void) { - int rc, fd, port; + int rc, fd; + evtchn_port_t port; unsigned long mfn; char str[20]; struct domain *dom0; diff --git a/xen/include/public/event_channel.h b/xen/include/public/event_channel.h index 1de1057512..bb15a87b7d 100644 --- a/xen/include/public/event_channel.h +++ b/xen/include/public/event_channel.h @@ -9,6 +9,8 @@ #ifndef __XEN_PUBLIC_EVENT_CHANNEL_H__ #define __XEN_PUBLIC_EVENT_CHANNEL_H__ +typedef uint32_t evtchn_port_t; + /* * EVTCHNOP_alloc_unbound: Allocate a port in domain and mark as * accepting interdomain bindings from domain . A fresh port @@ -20,9 +22,9 @@ #define EVTCHNOP_alloc_unbound 6 typedef struct evtchn_alloc_unbound { /* IN parameters */ - domid_t dom, remote_dom; + domid_t dom, remote_dom; /* OUT parameters */ - uint32_t port; + evtchn_port_t port; } evtchn_alloc_unbound_t; /* @@ -37,10 +39,10 @@ typedef struct evtchn_alloc_unbound { #define EVTCHNOP_bind_interdomain 0 typedef struct evtchn_bind_interdomain { /* IN parameters. */ - domid_t remote_dom; - uint32_t remote_port; + domid_t remote_dom; + evtchn_port_t remote_port; /* OUT parameters. */ - uint32_t local_port; + evtchn_port_t local_port; } evtchn_bind_interdomain_t; /* @@ -57,7 +59,7 @@ typedef struct evtchn_bind_virq { uint32_t virq; uint32_t vcpu; /* OUT parameters. */ - uint32_t port; + evtchn_port_t port; } evtchn_bind_virq_t; /* @@ -73,7 +75,7 @@ typedef struct evtchn_bind_pirq { #define BIND_PIRQ__WILL_SHARE 1 uint32_t flags; /* BIND_PIRQ__* */ /* OUT parameters. */ - uint32_t port; + evtchn_port_t port; } evtchn_bind_pirq_t; /* @@ -86,7 +88,7 @@ typedef struct evtchn_bind_pirq { typedef struct evtchn_bind_ipi { uint32_t vcpu; /* OUT parameters. */ - uint32_t port; + evtchn_port_t port; } evtchn_bind_ipi_t; /* @@ -97,7 +99,7 @@ typedef struct evtchn_bind_ipi { #define EVTCHNOP_close 3 typedef struct evtchn_close { /* IN parameters. */ - uint32_t port; + evtchn_port_t port; } evtchn_close_t; /* @@ -107,7 +109,7 @@ typedef struct evtchn_close { #define EVTCHNOP_send 4 typedef struct evtchn_send { /* IN parameters. */ - uint32_t port; + evtchn_port_t port; } evtchn_send_t; /* @@ -122,7 +124,7 @@ typedef struct evtchn_send { typedef struct evtchn_status { /* IN parameters */ domid_t dom; - uint32_t port; + evtchn_port_t port; /* OUT parameters */ #define EVTCHNSTAT_closed 0 /* Channel is not in use. */ #define EVTCHNSTAT_unbound 1 /* Channel is waiting interdom connection.*/ @@ -134,11 +136,11 @@ typedef struct evtchn_status { uint32_t vcpu; /* VCPU to which this channel is bound. */ union { struct { - domid_t dom; + domid_t dom; } unbound; /* EVTCHNSTAT_unbound */ struct { - domid_t dom; - uint32_t port; + domid_t dom; + evtchn_port_t port; } interdomain; /* EVTCHNSTAT_interdomain */ uint32_t pirq; /* EVTCHNSTAT_pirq */ uint32_t virq; /* EVTCHNSTAT_virq */ @@ -158,7 +160,7 @@ typedef struct evtchn_status { #define EVTCHNOP_bind_vcpu 8 typedef struct evtchn_bind_vcpu { /* IN parameters. */ - uint32_t port; + evtchn_port_t port; uint32_t vcpu; } evtchn_bind_vcpu_t; -- 2.30.2